﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Brin.Concurrent;

namespace Brin.Concurrent.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            PowerTestInt();

            PowerTestLong();

            MinTest();

            MaxTest();

            AndTest();

            OrTest();

            XORTest();

            TestBitAndSetTest();

            TestBitAndResetTest();

            ComputeAndSetTest();

            Console.ReadLine();
        }

        static void PowerTestInt()
        {
            int x = 2;
            int y = 30;

            MulInt m = new MulInt(x);

            Parallel.For(1, y, (i) =>
            {
                m.MultiplyTotal(x);
            });

            int result = m.Total;

            Console.WriteLine("{0} raised to the power of {1} = {2}.", x, y, result);

        }

        static void PowerTestLong()
        {
            long x = 2;
            long y = 30;

            MulLong m = new MulLong(x);

            Parallel.For(1, y, (i) =>
            {
                m.MultiplyTotal(x);
            });

            long result = m.Total;

            Console.WriteLine("{0} raised to the power of {1} = {2}.", x, y, result);
        }

        static void MinTest()
        {
            int a = 100;
            int b = 101;

            int res = InterlockedEx.Min(ref a, b);

            Console.WriteLine("the minimum of 100 and 101 = {0}.", res);
        }

        static void MaxTest()
        {
            int a = 100;
            int b = 101;

            int res = InterlockedEx.Max(ref a, b);

            Console.WriteLine("the maximum of 100 and 101 = {0}.", res);
        }

        static void AndTest()
        {
            int dest = 5;
            int with = 3;

            int res = InterlockedEx.And(ref dest, with);

            Console.WriteLine("5 AND 3 = {0}.", res);
        }

        static void OrTest()
        {
            int dest = 5;
            int with = 3;

            int res = InterlockedEx.Or(ref dest, with);

            Console.WriteLine("5 OR 3 = {0}.", res);
        }

        static void XORTest()
        {
            int dest = 5;
            int with = 3;

            int res = InterlockedEx.Xor(ref dest, with);

            Console.WriteLine("5 XOR 3 = {0}.", res);
        }

        static void TestBitAndSetTest()
        {
            int dest = 15;

            int res = InterlockedEx.TestBitAndSet(ref dest, 4);

            Console.WriteLine("15 bit 0 = {0}.", res);

            int initial = 0;
            Parallel.For(0, 32, pos =>
            {
                int bitValue = InterlockedEx.TestBitAndSet(ref initial, pos);
                Console.WriteLine("bitValue = {0}", bitValue);
            });

            Console.WriteLine("initial = {0}", initial);
        }

        static void TestBitAndResetTest()
        {
            int dest = 17;

            int res = InterlockedEx.TestBitAndReset(ref dest, 4);

            Console.WriteLine("15 bit 0 = {0}.", res);
            
            int initial = -1;
            Parallel.For(0, 32, pos =>
            {
                int bitValue = InterlockedEx.TestBitAndReset(ref initial, pos);
                Console.WriteLine("bitValue = {0}", bitValue);
            });

            Console.WriteLine("initial = {0}", initial);
        }

        static void ComputeAndSetTest()
        {
            int dest = 22;

            int res = InterlockedEx.ComputeAndSet(ref dest, val => val > 0, val => val *= 2);


            Console.WriteLine("ComputeAndSet destination = {0}", dest);
        }
    }
}
